package com.jee.ssm.modules.order.services;


import cn.hutool.http.HttpUtil;
import cn.hutool.setting.dialect.Props;
import com.alibaba.fastjson.JSON;
import com.jee.ssm.common.config.Logger;
import com.jee.ssm.common.socket.ZWSUtil;
import com.jee.ssm.model.*;
import com.jee.ssm.model.json.Tip;
import com.jee.ssm.model.param.ParamMap;
import com.jee.ssm.modules.black.dao.BlackDao;
import com.jee.ssm.modules.chargeRules.dao.ChargeRulesDao;
import com.jee.ssm.modules.order.dao.OrderDao;
import com.jee.ssm.modules.posUser.dao.PosUserDao;
import com.jee.ssm.modules.ssm.services.BaseService;
import com.github.pagehelper.PageInfo;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* 订单管理 Service
* @author GaoXiang
* @version 1.0
*/
@Service
public class OrderService extends BaseService<Order> {

    @Resource
    private OrderDao orderDao;
    @Resource
    private ChargeRulesDao chargeRulesDao;
    @Resource
    private BlackDao blackDao;
    @Resource
    private PosUserDao posUserDao;
    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
    * 保存数据
    * @param order 实体对象
    * @return 实体id
    * @throws Exception 数据保存异常
    */
    public Integer insert(Order order) throws Exception {
        return orderDao.insert(order);
    }

    /**
    * 根据 id 修改
    * @param order 带id的实体对象
    * @return 受影响的行数
    * @throws Exception 数据修改异常
    */
    public Integer updateById(Order order) throws Exception {
        return orderDao.updateById(order);
    }

    /**
    * 根据 id 删除
    * @param id 数据id
    * @return 受影响的行数
    * @throws Exception 数据删除异常
    */
    public Integer deleteById(String id) throws Exception {
        return orderDao.deleteById(id);
    }

    /**
    * 根据 id 查找
    * @param id 实体id
    * @return 实体
    */
    public Order selectById(String id) {
        return orderDao.selectById(id);
    }

    /**
    * 根据 id 批量删除
    * @param ids 要删除的id
    * @return 影响的行数
    * @throws Exception 数据删除异常
    */
    public Integer deleteByIds(List<String> ids) throws Exception {
        return orderDao.deleteByIds(ids);
    }

    /**
    * 查询列表
    * @param map 参数
    * @return 列表
    */
    public PageInfo<Order> list(Map map) {
        return orderDao.list(map);
    }

    /**
    * 查询列表 带分页
    * @param map 参数
    * @param page 页码
    * @param size 每页大小
    * @return 列表
    */
    public PageInfo<Order> list(Map map,int page,int size) {
        PageInfo<Order> pageInfo = orderDao.list(map,page,size);
        if(pageInfo.getList() != null && !pageInfo.getList().isEmpty()){
            for (Order order:pageInfo.getList()) {
                PosUser posUser = posUserDao.selectById(order.getPosUserId());
                if(posUser != null){
                    order.setManagerName(posUser.getPosUserName());
                }
            }
        }
        return orderDao.list(map,page,size);
    }


    public Tip normalBill(PassData passData){
        Double money = 0.00;
        int carType = 0;//默认小车
        if(passData.getVehType() != 1){
            carType = 1;//大车
        }
        String parkId = passData.getParkId();
        ParamMap paramMap = new ParamMap();
        paramMap.put("carType",carType);
        paramMap.put("parkId",parkId);
        ChargeRules chargeRules = chargeRulesDao.queryByParkAndcarType(paramMap);
        if (chargeRules != null){
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//格式化时间
            String passTime = format.format(passData.getInPassTime());
            String leaveTime = format.format(passData.getPassTime());
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime ldt = LocalDateTime.parse(passTime,formatter);
            LocalDateTime ldt2 = LocalDateTime.parse(leaveTime,formatter);//可获时间的月份，但是要求时间格式"yyyy-MM-dd HH:mm:ss"
            int passTimeYear = ldt.getYear();//入场年份
            int passTimeMonth = ldt.getMonth().getValue();//入场月份
            int passTimeDay = ldt.getDayOfMonth();//入场日
            int leaveTimeYear = ldt2.getYear();//离场年份
            int leaveTimeMonth = ldt2.getMonth().getValue();//离场月份
            int leaveTimeDay = ldt2.getDayOfMonth();//离场日
            int sumDay = leaveTimeDay - passTimeDay;//停了几天
            int sumMonth = leaveTimeMonth - passTimeMonth;//停了几个月（针对跨月份停车）
            if (sumMonth == 0){//没跨月份，当月停当月走
                if (sumDay == 0 ){//当天停当天走
                    money = getMoney(chargeRules,sumDay+1,passData.getPassTime(),passData.getInPassTime());
                }else if (sumDay>0){//停了一天以上
                    money = getMoney(chargeRules,sumDay+1,passData.getPassTime(),passData.getInPassTime());
                }
            }else if(sumMonth != 0){//跨月份停车了
                if (passTimeMonth==1||passTimeMonth==3||passTimeMonth==5||passTimeMonth==7||passTimeMonth==8||passTimeMonth==10||passTimeMonth==12){//31天的月份
                    sumDay = 31 - passTimeDay + leaveTimeDay ;
                    money = getMoney(chargeRules,sumDay+1,passData.getPassTime(),passData.getInPassTime());
                }else if (passTimeMonth==4||passTimeMonth==6||passTimeMonth==9||passTimeMonth==11){//30天的月份
                    sumDay = 30 - passTimeDay + leaveTimeDay;
                    money = getMoney(chargeRules,sumDay+1,passData.getPassTime(),passData.getInPassTime());
                }else if (passTimeMonth==2){
                    if((passTimeYear%4==0&&passTimeYear%100!=0)||passTimeYear%400==0) {//闰年
                        sumDay = 29 - passTimeDay + leaveTimeDay;
                        money = getMoney(chargeRules,sumDay+1,passData.getPassTime(),passData.getInPassTime());
                    }else {//不是闰年
                        sumDay = 28 - passTimeDay + leaveTimeDay;
                        money = getMoney(chargeRules,sumDay+1,passData.getPassTime(),passData.getInPassTime());
                    }
                }
            }
            return new Tip(money);
        }else {
            return new Tip(1,"当前停车场没有启用收费规则！");
        }

    }

    /**
     * 计算停车费用
     * @param chargeRules
     * @param day
     * @param passTime
     * @param leaveTime
     * @return
     */
    private Double getMoney(ChargeRules chargeRules, int day, Date leaveTime, Date passTime){
        long time = leaveTime.getTime() - passTime.getTime();
        Double money = 0.00;
        if (chargeRules.getBuyType()==0){//按次计费
            if (time/60000 > chargeRules.getFreeTime()){//如果超过了免费停车时长
                money = chargeRules.getPayMoney() * day;
            }
        }else if (chargeRules.getBuyType() == 1){//按时间计费
            if (day == 1){ //按时计费没超过一日
                long passLong = passTime.getTime()/60000;
                long leaveLong =  leaveTime.getTime()/60000;
                long stopTime = leaveLong - passLong;
                long outTime = leaveLong - passLong;//总时长
                if (stopTime>chargeRules.getFreeTime()){//超过免费时长
                    stopTime = stopTime - chargeRules.getFreeTime();
                    if (stopTime>chargeRules.getFirstPayTime()){//超过首段收费时长
                        stopTime = outTime - chargeRules.getFirstPayTime();
                        money = money + chargeRules.getFirstPayMoney();
                        for ( ; stopTime>0 ; stopTime -= chargeRules.getIntervalTime()){
                            money = money + chargeRules.getIntervalMoney();
                            if (chargeRules.getMaxStatus()==1){//启用封顶金额
                                if (money>chargeRules.getMaxMoney()){
                                    money = chargeRules.getMaxMoney();
                                    break;
                                }
                            }
                        }
                    }else {
                        money = money + chargeRules.getFirstPayMoney();
                    }
                }
            }else if (day>1){//按时计费超过了一日
                long passLong = passTime.getTime()/60000;
                long leaveLong = leaveTime.getTime()/60000;
                long stopTime = leaveLong - passLong - chargeRules.getFreeTime();
                Double summoney = chargeRules.getFirstPayMoney();
                Double firstDayMoney = 0.00;
                Double lastDayMoney = 0.00;
                DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//格式化时间
                String passTimeString = format.format(passTime);
                String leaveTimeString = format.format(leaveTime);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                LocalDateTime ldt = LocalDateTime.parse(passTimeString,formatter);
                LocalDateTime ldt2 = LocalDateTime.parse(leaveTimeString,formatter);//可获时间的月份，但是要求时间格式"yyyy-MM-dd HH:mm:ss"

                int a = 60 - ldt.getMinute();
                int b = 23 - ldt.getHour();
                int firstDayStopTime = a+b*60 - chargeRules.getFirstPayTime();//第一天停了多久

                for (int j = 0  ; j < firstDayStopTime ; j+=chargeRules.getIntervalTime()){//计算出第一天费用
                    firstDayMoney = firstDayMoney + chargeRules.getIntervalMoney();
                    if (chargeRules.getMaxStatus()==1){//启用封顶金额
                        if (firstDayMoney>chargeRules.getMaxMoney()){
                            firstDayMoney = chargeRules.getMaxMoney();
                            break;
                        }
                    }
                }

                int c = ldt2.getMinute();
                int d = ldt2.getHour();
                int lastDayStopTime = c + d*60;// 最后一天停了多久

                for (int k = 0  ; k < lastDayStopTime ; k+=chargeRules.getIntervalTime()){//计算出第一天费用
                    lastDayMoney = lastDayMoney + chargeRules.getIntervalMoney();
                    if (chargeRules.getMaxStatus()==1){//启用封顶金额
                        if (lastDayMoney>chargeRules.getMaxMoney()){
                            lastDayMoney = chargeRules.getMaxMoney();
                            break;
                        }
                    }
                }
                if (chargeRules.getMaxStatus()==1){//启用封顶金额
                    summoney = summoney + firstDayMoney + lastDayMoney +( (day-2)* chargeRules.getMaxMoney());
                }else {
                    summoney = summoney + firstDayMoney + lastDayMoney +( (day-2)*1440/chargeRules.getIntervalTime()*chargeRules.getIntervalMoney());//
                }
                return summoney;
            }
        }else if (chargeRules.getBuyType() == 2){//日夜分时计费
            if (day==1){//没超过一日
                DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//格式化时间
                String passTimeString = format.format(passTime);
                String leaveTimeString = format.format(leaveTime);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                LocalDateTime ldt = LocalDateTime.parse(passTimeString,formatter);
                LocalDateTime ldt2 = LocalDateTime.parse(leaveTimeString,formatter);//可获时间的月份，但是要求时间格式"yyyy-MM-dd HH:mm:ss"
                int nightTime = Integer.valueOf(chargeRules.getNightStartTime().substring(0,2));
                if (ldt.getHour()>=nightTime){//夜间进入
                    money = money + chargeRules.getPayMoney();
                }
                if (ldt.getHour()<nightTime){//白天进入
                    ldt.getHour();
                }

            }else {//超过了一日

            }
        }else {//不收费

        }
        return money;
    }

    /**
     * 处理支付宝/微信回调的业务的逻辑
     *
     * 付款方式（0，支付宝；1，微信；2，余额,3.现金，4停车场内支付）
     */
    public  void handleCallBack(String outTradeNo, int payType, HttpServletRequest request,String qz){
       String codeUrl = request.getSession().getServletContext().getRealPath("")+"/images/qrcode/"+qz+outTradeNo+".jpg";  //真实支付图片的二维码
        System.out.println("二维码的真实路径："+codeUrl);
        File file = new File(codeUrl);
        file.delete();
        String orderId = outTradeNo.split("_")[0];//订单的编号
        System.out.println("订单编号："+orderId);
        Order order = orderDao.selectById(orderId);
        if(order !=null){

            //查询是否是逃缴订单
            Black black = blackDao.selectByOrderId(orderId);

            order.setPayType(payType);
            order.setOrderStatus(1);
            order.setPayTime(new Date());
            try {
                String sbCode = order.getSbCode();//终端机的编号
                Map<String,Object> map = new HashMap<>();
                map.put("type","0");//支付完成通知手持机
//                if (ZWSUtil.wssMap != null && ZWSUtil.wssMap.get(sbCode) != null){
//                    ZWSUtil.wssMap.get(sbCode).getWebSocketSession().sendMessage((new TextMessage(JSON.toJSONString(map))));
//                }
                amqpTemplate.convertAndSend(sbCode,JSON.toJSONString(map));//mq推送支付成功状态
                //修改订单状态
                orderDao.updateById(order);

                //删除黑名单记录
                if(black != null) blackDao.deleteById(black.getId());

                //更新服务器订单状态
                Map params = new HashMap();
                params.put("id", order.getId());
                params.put("payType",payType);
                params.put("orderStatus",1);
                Props props = new Props("config/project.properties");
                String serverUrl =props.getProperty("server.url"); //停车服务的地址
                String  method = props.getProperty("tc.updateOrder");
                String str = HttpUtil.get(serverUrl + method, params);
                Logger.info("订单同步(服务器)："+str);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @Description 根据收费员id获取订单列表
     * @author yanzengbao
     * @date 2019/8/16 上午9:34
     */
    public List<Order> selectByPosUserId(String userId) {
        return orderDao.selectByPosUserId(userId);
    }
    /**
     * @Description 根据收费员id获取订单列表
     * @author yanzengbao
     * @date 2019/8/16 上午9:34
     */
    public List<Order> selectBySbCode(Order order) {
        return orderDao.selectBySbCode(order);
    }

    /**
     *根据手持机编号获取当日所有金额
     * @param order
     * @return
     */
    public Order getAllPayMoney(Order order){return orderDao.getAllPayMoney(order);}

    /**
     *根据手持机编号获取当日wei支付金额
     * @param order
     * @return
     */
    public Order getUnPayMoney(Order order){return orderDao.getUnPayMoney(order);}

    /**
     *根据手持机编号获取当日已支付金额
     * @param order
     * @return
     */
    public Order getPayMoney(Order order){return orderDao.getPayMoney(order);}/**
     *根据手持机编号获取当日逃缴金额
     * @param order
     * @return
     */
    public Order getRunAway(Order order){return orderDao.getRunAway(order);}

    /**
     * 描述： 搜索查询订单（根据停车场ID和车牌号查询近一周没有支付状态的订单）
     * 创建时间：2021/4/25  YanZengBao
     * 修改时间：2021/4/25  YanZengBao 加注释
     * 修改时间：
     */
    public List<Order> selectSousou(Map map) {
        return orderDao.selectSousou(map);
    }
}
